package cn.edu.sgu.www.mhxysy.service.xingyin.impl;

import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.consts.CustomMessages;
import cn.edu.sgu.www.mhxysy.dto.xingyin.XingyinDTO;
import cn.edu.sgu.www.mhxysy.entity.xingyin.Xingyin;
import cn.edu.sgu.www.mhxysy.entity.xingyin.XingyinAttribute;
import cn.edu.sgu.www.mhxysy.entity.xingyin.XingyinViewAttribute;
import cn.edu.sgu.www.mhxysy.function.computer.score.impl.XingyinScoreComputer;
import cn.edu.sgu.www.mhxysy.mapper.xingyin.XingyinAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.xingyin.XingyinMapper;
import cn.edu.sgu.www.mhxysy.mapper.xingyin.XingyinViewAttributeMapper;
import cn.edu.sgu.www.mhxysy.service.xingyin.XingyinService;
import cn.edu.sgu.www.mhxysy.util.MathUtils;
import cn.edu.sgu.www.mhxysy.util.ObjectUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class XingyinServiceImpl implements XingyinService {

    private final XingyinMapper xingyinMapper;
    private final XingyinScoreComputer xingyinScoreComputer;
    private final XingyinAttributeMapper xingyinAttributeMapper;
    private final XingyinViewAttributeMapper xingyinViewAttributeMapper;

    @Autowired
    public XingyinServiceImpl(
            XingyinMapper xingyinMapper,
            XingyinScoreComputer xingyinScoreComputer,
            XingyinAttributeMapper xingyinAttributeMapper,
            XingyinViewAttributeMapper xingyinViewAttributeMapper) {
        this.xingyinMapper = xingyinMapper;
        this.xingyinScoreComputer = xingyinScoreComputer;
        this.xingyinAttributeMapper = xingyinAttributeMapper;
        this.xingyinViewAttributeMapper = xingyinViewAttributeMapper;
    }

    @Override
    public void compute(String xingyinId) {
        UpdateWrapper<Xingyin> updateWrapper = new UpdateWrapper<>();

        updateWrapper.eq("id", xingyinId);
        updateWrapper.set("score", xingyinScoreComputer.compute(xingyinId));

        xingyinMapper.update(updateWrapper.getEntity(), updateWrapper);
    }

    @Override
    public void insert(XingyinDTO xingyinDTO) {
        /*
         * 1、添加星印
         */
        Xingyin xingyin = toEntity(xingyinDTO);

        xingyin.setId(xingyin.uuid());

        xingyinMapper.insert(xingyin);

        /*
         * 2、添加星印属性
         */
        // 获取星印的预览属性中的基础属性
        Map<String, Object> columnMap = new HashMap<>();

        columnMap.put("type", 1);
        columnMap.put("xingyin_id", xingyin.getCategoryId());

        List<XingyinViewAttribute> list = xingyinViewAttributeMapper.selectByMap(columnMap);

        // 生成随机下标，获取随机的基础属性
        int random = MathUtils.random(0, list.size() - 1);
        XingyinViewAttribute viewAttribute = list.get(random);

        // 1、添加基础属性
        XingyinAttribute xingyinAttribute = new XingyinAttribute();

        xingyinAttribute.setType(1);
        xingyinAttribute.setId(xingyinAttribute.uuid());
        xingyinAttribute.setXingyinId(xingyin.getId());
        xingyinAttribute.setPropertyId(viewAttribute.getPropertyId());
        xingyinAttribute.setPropertyValue(MathUtils.random(viewAttribute.getMin(), viewAttribute.getMax()));

        xingyinAttributeMapper.insert(xingyinAttribute);

        // 2、鉴定属性
        // 获取星印的预览属性中的鉴定属性
        columnMap.put("type", 2);

        list = xingyinViewAttributeMapper.selectByMap(columnMap);

        /*
         * 生成随机数，用于获取随机的鉴定属性条数，2~3条
         * 1/10概率获得3词条
         */
        int count = MathUtils.random(1, 10) == 5 ? 3: 2;

        for (int i = 0; i < count; i++) {
            // 生成随机的鉴定属性
            int index = MathUtils.random(0, list.size() - 1);

            XingyinViewAttribute xingyinViewAttribute = list.get(index);

            // 往数据库插入数据
            xingyinAttribute = new XingyinAttribute();

            xingyinAttribute.setType(2);
            xingyinAttribute.setXingyinId(xingyin.getId());
            xingyinAttribute.setId(xingyinAttribute.uuid() + (i + 1));
            xingyinAttribute.setPropertyId(xingyinViewAttribute.getPropertyId());
            // 设置随机的属性值
            xingyinAttribute.setPropertyValue(
                    MathUtils.random(
                            xingyinViewAttribute.getMin(), xingyinViewAttribute.getMax()
                    )
            );

            xingyinAttributeMapper.insert(xingyinAttribute);
        }
    }

    @Override
    public void deleteById(String xingyinId) {
        // 1、删除星印属性
        QueryWrapper<XingyinAttribute> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("xingyin_id", xingyinId);

        xingyinAttributeMapper.delete(queryWrapper);

        // 2、删除星印
        xingyinMapper.deleteById(xingyinId);
    }

    @Override
    public void updateById(XingyinDTO xingyinDTO) {
        ObjectUtils.requireNonNull(xingyinDTO.getId(), CustomMessages.ID_NOT_NULL);

        Xingyin xingyin = toEntity(xingyinDTO);

        xingyinMapper.updateById(xingyin);
    }

    @Override
    public Page<Xingyin> selectByPage(Pager<Xingyin> pager) {
        QueryWrapper<Xingyin> queryWrapper = Pager.getQueryWrapper(pager);
        Page<Xingyin> page = Pager.ofPage(pager);

        queryWrapper.orderByAsc("role_id", "category_id");

        return xingyinMapper.selectPage(page, queryWrapper);
    }

    private Xingyin toEntity(XingyinDTO xingyinDTO) {
        Xingyin xingyin = new Xingyin();

        xingyin.setId(xingyinDTO.getId());
        xingyin.setScore(xingyinDTO.getScore());
        xingyin.setForger(xingyinDTO.getForger());
        xingyin.setRoleId(xingyinDTO.getRoleId());
        xingyin.setDurability(xingyinDTO.getDurability());
        xingyin.setTexiaoId(xingyinDTO.getTexiaoId());
        xingyin.setCategoryId(xingyinDTO.getCategoryId());
        xingyin.setWearStatus(xingyinDTO.getWearStatus());

        return xingyin;
    }

}